@let activeEnvironment = activeEnvironment$ | async;
@let activeRoute = activeRoute$ | async;
@let duplicatedRoutes = duplicatedRoutes$ | async;
@let disabledRoutes = disabledRoutes$ | async;
@let collapsedFolders = collapsedFolders$ | async;
@let settings = settings$ | async;
@let routesFilter = routesFilter$ | async;
@let isActiveEnvironmentCloud = isActiveEnvironmentCloud$ | async;

<div
  class="routes-menu d-flex flex-column h-100"
  appTourStep="tour-routes-menu"
>
  <div class="d-flex w-100 py-2 align-items-center">
    <div ngbDropdown id="routes-add-dropdown" appTourStep="tour-route-add">
      <button
        class="btn btn-link dropdown-toggle dropdown-toggle-icon"
        type="button"
        ngbDropdownToggle
      >
        <app-svg icon="add_box"></app-svg>
      </button>
      <div class="dropdown-menu" id="routes-add-dropdown-menu" ngbDropdownMenu>
        <button class="btn dropdown-item" (click)="addCRUDRouteTemplate()">
          <app-svg icon="magic" class="me-1"></app-svg> Assistants and templates
        </button>
        <button class="btn dropdown-item" (click)="addCRUDRoute()">
          <app-svg icon="endpoints" class="me-1"></app-svg> CRUD route
        </button>
        <button class="btn dropdown-item" (click)="addHTTPRoute()">
          <app-svg icon="endpoint" class="me-1"></app-svg> HTTP route
        </button>
        @if (!isActiveEnvironmentCloud) {
          <button class="btn dropdown-item" (click)="addWebSocketRoute()">
            <app-svg icon="websocket" class="me-1"></app-svg> WebSocket
          </button>
        }
        <button class="btn dropdown-item" (click)="addFolder()">
          <app-svg icon="folder" class="me-1"></app-svg> Folder
        </button>
      </div>
    </div>

    <div class="flex-grow-1">
      <app-filter
        filterName="routes"
        [focusableInput]="focusableInputs.ROUTE_FILTER"
      ></app-filter>
    </div>
  </div>

  @defer {
    @let rootFolder = rootFolder$ | async;

    @if (rootFolder) {
      <ul #routesMenu class="nav flex-column menu-list h-100">
        <ng-container
          [ngTemplateOutlet]="foldersTemplate"
          [ngTemplateOutletContext]="{
            folder: rootFolder
          }"
        >
        </ng-container>
      </ul>
    }

    <!-- Recursive folder template (first use is for the root level, some props will be undefined) -->
    <ng-template
      #foldersTemplate
      let-folder="folder"
      let-parentId="parentId"
      let-parentChainId="parentChainId"
      let-level="level"
    >
      @for (child of folder.children; track child.data.uuid) {
        @if (child.type === 'folder') {
          <ng-container
            [ngTemplateOutlet]="folderItemTemplate"
            [ngTemplateOutletContext]="{
              folder: child.data,
              parentId: parentId === undefined ? 'root' : parentId,
              parentChainId:
                parentChainId === undefined ? ['root'] : parentChainId,
              level: level === undefined ? 0 : level
            }"
          >
          </ng-container>
        } @else if (child.type === 'route') {
          <ng-container
            [ngTemplateOutlet]="routeItemTemplate"
            [ngTemplateOutletContext]="{
              route: child.data,
              isHidden$: child.isHidden$,
              parentId: parentId === undefined ? 'root' : parentId,
              parentChainId:
                parentChainId === undefined ? ['root'] : parentChainId,
              level: level === undefined ? 0 : level
            }"
          ></ng-container>
        }
      }
    </ng-template>

    <!-- Folder item template -->
    <ng-template
      #folderItemTemplate
      let-folder="folder"
      let-parentId="parentId"
      let-parentChainId="parentChainId"
      let-level="level"
    >
      <li
        class="nav-item"
        [ngClass]="{ 'd-none': routesFilter }"
        appDraggable
        appDropzone
        dragContainer="routes"
        [dragEnabled]="dragEnabled"
        [dragParentId]="parentId"
        [dragParentChainId]="parentChainId"
        [dragIsContainer]="true"
        [dragId]="folder.uuid"
        (dropped)="reorderRoutes($event)"
      >
        <!-- Calculate padding of 2 rem + 0.5 (gap between the folder icon and folder name) -->
        <a
          class="nav-link d-flex pe-0 hover-parent"
          [ngStyle]="{
            'padding-left.rem':
              routesFilter || !level ? undefined : level * 2 + 0.5
          }"
          appScrollWhenActive
          [formGroup]="folderForm"
          (click)="toggleCollapse(folder)"
        >
          <div class="pe-2">
            <app-svg
              [icon]="
                collapsedFolders.includes(folder.uuid)
                  ? 'folder'
                  : 'folder_open'
              "
            ></app-svg>
          </div>
          <app-editable-element
            [ngClass]="{
              'text-truncate': settings.truncateRouteName,
              'text-break': !settings.truncateRouteName
            }"
            [text]="folder.name"
            formControlName="name"
            (editChange)="editFolder(folder, $event)"
          ></app-editable-element>
          <div class="ms-auto">
            <app-dropdown-menu
              [idPrefix]="'folder-' + folder.uuid"
              [items]="folderDropdownMenuItems"
              [payload]="{
                folder,
                folderUuid: folder.uuid
              }"
              [iconFaded]="true"
              [noYPadding]="true"
            ></app-dropdown-menu>
          </div>
        </a>
      </li>

      <!-- Display sub items if folder is not collapsed or if a search is in progress -->
      @if (!collapsedFolders.includes(folder.uuid) || routesFilter) {
        @if (folder.children.length === 0) {
          <li class="nav-item" [ngClass]="{ 'd-none': routesFilter }">
            <!-- Calculate padding of 2 rem + 0.5 (gap between the folder icon and folder name) -->
            <a
              class="nav-link disabled"
              [ngStyle]="{
                'padding-left.rem': routesFilter
                  ? undefined
                  : (level + 1) * 2 + 0.5
              }"
              >Folder is empty</a
            >
          </li>
        } @else if (folder.children.length > 0) {
          <!-- Display sub items -->
          <ng-container
            [ngTemplateOutlet]="foldersTemplate"
            [ngTemplateOutletContext]="{
              folder: folder,
              parentId: folder.uuid,
              parentChainId: parentChainId.concat(folder.uuid),
              level: level + 1
            }"
          >
          </ng-container>
        }
      }
    </ng-template>

    <!-- Route item template -->
    <ng-template
      #routeItemTemplate
      let-route="route"
      let-isHidden$="isHidden$"
      let-parentId="parentId"
      let-parentChainId="parentChainId"
      let-level="level"
    >
      <li
        class="nav-item"
        [ngClass]="{ 'd-none': isHidden$ | async }"
        appDraggable
        appDropzone
        dragContainer="routes"
        [dragEnabled]="dragEnabled"
        [dragParentId]="parentId"
        [dragParentChainId]="parentChainId"
        [dragIsContainer]="false"
        [dragId]="route.uuid"
        (dropped)="reorderRoutes($event)"
      >
        <!-- Calculate padding of 2 rem + 0.5 (gap between the folder icon and folder name) -->
        <a
          class="nav-link d-flex pe-0 hover-parent"
          [ngStyle]="{
            'padding-left.rem':
              routesFilter || !level ? undefined : level * 2 + 0.5
          }"
          [ngClass]="{
            active: activeRoute?.uuid === route.uuid,
            'route-disabled': disabledRoutes.includes(route.uuid)
          }"
          appScrollWhenActive
          (click)="selectRoute(route.uuid)"
        >
          <!-- mw0 is important for proper text truncation -->
          <div class="d-flex flex-column mw0">
            <div
              class="nav-link-label"
              [ngClass]="{
                'text-truncate': settings.truncateRouteName,
                'text-break': !settings.truncateRouteName
              }"
            >
              /{{ route.endpoint }}
            </div>
            <div
              class="nav-link-subtitle mt-1 d-flex align-items-center svg-text-align"
            >
              <span
                class="color-method-{{
                  route.type === 'crud'
                    ? 'crud'
                    : route.type === 'ws'
                      ? 'ws'
                      : route.method
                }} me-2"
                >{{
                  route.type === 'crud'
                    ? 'CRUD'
                    : route.type === 'ws'
                      ? 'WS'
                      : (route.method | uppercase)
                }}
              </span>

              @if (route.responseMode === ResponseMode.RANDOM) {
                <app-svg
                  class="text-primary me-2"
                  icon="shuffle"
                  size="14"
                  ngbTooltip="Random response mode activated"
                ></app-svg>
              } @else if (route.responseMode === ResponseMode.SEQUENTIAL) {
                <app-svg
                  class="text-primary me-2"
                  icon="repeat"
                  size="14"
                  ngbTooltip="Sequential response mode activated"
                ></app-svg>
              } @else if (route.responseMode === ResponseMode.DISABLE_RULES) {
                <app-svg
                  class="text-warning me-2"
                  icon="rule"
                  size="14"
                  ngbTooltip="Disabled rules mode activated"
                ></app-svg>
              } @else if (route.responseMode === ResponseMode.FALLBACK) {
                <app-svg
                  class="text-primary me-2"
                  icon="low_priority"
                  size="14"
                  ngbTooltip="Fallback mode activated"
                ></app-svg>
              }

              @if (duplicatedRoutes[activeEnvironment.uuid]?.has(route.uuid)) {
                <app-svg
                  class="text-warning me-2"
                  icon="warning"
                  size="12"
                  ngbTooltip="Route is duplicated (same endpoint and method)"
                ></app-svg>
              }

              <span class="text-truncate">
                {{
                  route.documentation
                    ? route.documentation
                    : route.responses.length > 1
                      ? route.responses.length + ' responses'
                      : route.responses.length + ' response'
                }}
              </span>
            </div>
          </div>
          <div class="ms-auto ps-2 d-flex align-items-start">
            <app-dropdown-menu
              [idPrefix]="'route-' + route.uuid"
              [items]="routeDropdownMenuItems"
              [payload]="{
                parentId,
                routeUuid: route.uuid
              }"
              [iconFaded]="true"
              [noYPadding]="true"
            ></app-dropdown-menu>
          </div>
        </a>
      </li>
    </ng-template>
  }

  <div
    appResizeColumn
    type="secondary"
    [minWidth]="menuSize"
    [maxWidthFactor]="0.25"
    class="resize-column"
  ></div>
</div>
